package com.gwl.circle.user.service.impl;

import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gwl.circle.common.bo.UserAddBo;
import com.gwl.circle.common.bo.UserLoginBo;
import com.gwl.circle.common.config.SystemConfig;
import com.gwl.circle.common.util.CircleUtils;
import com.gwl.circle.common.vo.R;
import com.gwl.circle.user.dao.UserDao;
import com.gwl.circle.user.dao.UserDetailDao;
import com.gwl.circle.user.dao.UserLogDao;
import com.gwl.circle.user.entity.User;
import com.gwl.circle.user.entity.UserDetail;
import com.gwl.circle.user.entity.UserLog;
import com.gwl.circle.user.service.UserService;
import com.gwl.circle.user.util.JwtUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @Author 高万里
 */
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserDao dao;

    @Resource
    private UserLogDao logDao;

    @Resource
    private UserDetailDao detailDao;

    @Resource
    private StringRedisTemplate template;

    @Override
    @Transactional
    public R register(UserAddBo bo, String ip) {
        if (Objects.nonNull(bo)) {
            if (Objects.isNull(dao.selectOne(new LambdaQueryWrapper<User>().eq(User::getName, bo.getName())))) {
                User user = new User();
                BeanUtils.copyProperties(bo, user);
                user.setFlag(1);
                user.setPassword(SecureUtil.sha256(SecureUtil.md5(bo.getPassword())));
                if (dao.insert(user) > 0) {
                    UserLog log = new UserLog(user.getId(), SystemConfig.LOG_REGISTER, "注册了账号", ip);
                    detailDao.insert(new UserDetail(user.getId(), 1, SystemConfig.GROW_REGISTER));
                    logDao.insert(log);
                    return R.ok();
                }
                return R.fail("注册失败！");
            }
            return R.fail("用户名已存在");
        }

        return R.fail("为啥失败自己想");
    }

    @Override
    public R Login(UserLoginBo bo, String ip) {
        if (Objects.nonNull(bo)) {
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            String pass = SecureUtil.sha256(SecureUtil.md5(bo.getPassword()));
            User user = dao.selectOne(wrapper.eq(User::getName, bo.getName()).eq(User::getPassword, pass));
            if (Objects.nonNull(user)) {
                String token = JwtUtil.createJwt(user.getId() + "");
                template.opsForValue().set(SystemConfig.REDIS_TOKEN + token, user.getId() + "", 30, TimeUnit.MINUTES);
                logDao.insert(new UserLog(user.getId(), SystemConfig.LOG_LOGIN, "完成登录", ip));
                UserLog log = logDao.selectOne(new LambdaQueryWrapper<UserLog>().eq(UserLog::getUid, user.getId()).eq(UserLog::getType, SystemConfig.LOG_LOGIN).orderByDesc(UserLog::getCtime).last("limit 1"));
                if (Objects.nonNull(log) && !CircleUtils.difDate(log.getCtime(), new Date())) {

                }
                return R.ok(token);
            }
            return R.fail("账号或密码错误！");
        }
        return R.fail("信息错误，登录失败！");
    }

    @Override
    public R all() {
        return R.ok(dao.selectList(null));
    }

    @Override
    public R queryByToken(String token) {
        String uid = template.opsForValue().get(SystemConfig.REDIS_TOKEN + token);
        if (StringUtils.hasLength(uid)) {
            return R.ok(detailDao.selectList(new LambdaQueryWrapper<UserDetail>().eq(UserDetail::getUid, uid)));
        }
        return R.fail("无效的token");
    }

    @Override
    public R Logout(String token) {
        if (Boolean.TRUE.equals(template.hasKey(SystemConfig.REDIS_TOKEN + token))) {
            template.delete(SystemConfig.REDIS_TOKEN + token);
            return R.ok();
        }
        return R.fail("小子，你在请求接口！");
    }
}
